package com.hc.security;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hc.domain.User;
import com.hc.service.UserService;
import com.hc.utils.RedisUtil;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 服务实现类
 * 这个类可以和自定义的UserServiceImpl合并
 * @author 梁云亮
 */
@Service
public class MyUserDetailService implements UserDetailsService {

    @Resource
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.getUserByUsername(username);
        if(user==null){
            throw new UsernameNotFoundException("用户名错误！！");
        }
        //获取用户权限，并把其添加到GrantedAuthority中
        List<GrantedAuthority> authorityList = getGrantedAuthorities(user);
        org.springframework.security.core.userdetails.User account = new org.springframework.security.core.userdetails.User(username, user.getPassword(), authorityList);
        return account;
    }

    @Resource
    private RedisUtil redisUtil;

    /**
     * 获取指定用户的权限（Role+Permission）信息
     *
     * @param user
     * @return
     */
    public List<GrantedAuthority> getGrantedAuthorities(User user) {
        if (user == null) {
            throw new UsernameNotFoundException("用户名或密码不正确");
        }
        String authority = "";
        //先判断缓存中是否有当前用户的权限信息
        if (redisUtil.hasKey("GrantedAuthority:" + user.getId())) { //有从缓存中获取
            authority = redisUtil.get("GrantedAuthority:" + user.getId()).toString();
            //TODO:用户角色发生变化、角色编码发生变化、用户权限发生变化、权限编码发生改变时，需要修改缓存中的authority
        } else {//没有从数据库中获取
            //获取用户权限信息（角色、菜单权限）
            authority = userService.getUserAuthority(user.getId());
            redisUtil.set("GrantedAuthority:" + user.getId(), authority, 3600); // 1个小时
        }

        List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(authority.substring(0, authority.length() - 1));
        return authorityList;
    }

    /**
     * 清空指定用户在Redis中缓存的权限信息
     * @param userId 用户编号
     */
    public void clearAuthorityByUserId(Integer userId){
        redisUtil.del(List.of("GrantedAuthority:" + userId));
    }
    /**
     * 清空拥有指定Role的 用户在Redis中缓存的权限信息
     * @param roleId 用户编号
     */
    public void clearAuthorityByRoleId(Integer roleId){
        List<Integer> userIds = userService.getUserIdsByRoleId(roleId);
        List<String> ids = userIds.stream().map(item -> "GrantedAuthority:" + item).collect(Collectors.toList());
        redisUtil.del(ids);
    }

    /**
     * 清空拥有指定Permission的 用户在Redis中缓存的权限信息
     * @param permissionId 用户编号
     */
    public void clearAuthorityByPermissionId(Integer permissionId){
        List<Integer> permissionIds = userService.getUserIdsByPermissionId(permissionId);
        List<String> ids = permissionIds.stream().map(item -> "GrantedAuthority:" + item).collect(Collectors.toList());
        redisUtil.del(ids);
    }
}
